クラスメソッドのReact事情大公開スペシャル#4 -「App Router を実プロダクトで採用して見えてきた勘所をちょっとだけ紹介」というテーマで登壇しました #cm_react

クラスメソッドのReact事情大公開スペシャル#4 -「App Router を実プロダクトで採用して見えてきた勘所をちょっとだけ紹介」というテーマで登壇しました #cm_react

Clock Icon2024.09.09

先日、「クラスメソッドのReact事情大公開スペシャル#4」というイベントにて、「App Router を実プロダクトで採用して見えてきた勘所をちょっとだけ紹介」というテーマで登壇しました。

https://classmethod.connpass.com/event/325518/

イベントレポートはこちら
https://dev.classmethod.jp/articles/classmethod-react-big-reveal-special-4/

登壇資料

登壇資料はこちらです。

App Router 使ってる?

最初にこの質問をご来場のみなさんに聞いてみました。
トータルで40人ほどの人数だったかと思いますが、手が上がったのは2~3人程度という状態でした。
全体的な雰囲気を見るとやはり実務で取り入れるにはまだまだハードルが高そうです。
(個人的には取り入れている方の意見も聞いてみたいです。)

良かったこと

主観を大いに含んではいますが、クライアントで扱うステートがかなり削減されたことが大きいです。

例えばデータフェッチをするコンポーネントをクライアントコンポーネントだけで実装しようとした場合、特にフロントエンドにそこまで習熟していないエンジニアがコンポーネント設計を行うと、一つのコンポーネントでデータフェッチもその後の状態管理も行うようなコンポーネント設計をしてしまう余地があると思います。

サーバーコンポーネントを軸に設計すると、多くの場合データフェッチとその後の状態管理は分離して設計する必要があり、明確に責務が分離されるようになりました。

また、これは当日話し忘れましたが、(サーバーをどこに配置するかにも依りますが)Next.jsのバックエンドサーバーとデータソースとの距離が近づくことでレイテンシが低くなるのも地味に嬉しいです。

あとは個人的にはサーバーサイドでテンプレートエンジンをゴリゴリ書いていた人間なので、FormDataの扱いなどはなんとなくその頃を彷彿とさせるような形になっている気がします。
サーバーサイドで解決できるものが多いと安心します。

苦労したこと

トータルでは良かったと感じてはいるものの、そう思えるまでに色々と苦労した部分もありました。

一言で言ってしまえば圧倒的にノウハウが足りていませんでした。
最近は比較的事例を聞くようになってきましたが、2024年の4月頃から開発が始まったので当時は公式ドキュメントをベースに手探りで実装しているような形でした。

細かい内容は各種トピックがあるのですが、全て紹介すると持ち時間を大幅に超えてしまうため、ライブラリとの相性問題の話に絞ってお話しました。

ちなみにApp Router関係なく、Reactでのフロントエンド開発全般に関しての話は第一回にしておりますので、こちらも適宜ご参照ください。

https://dev.classmethod.jp/articles/classmethod-study-meeting-osaka-frontend-for-long-term-operation/

UIコンポーネントライブラリとの相性

理想としてはTailwind CSSなどのCSSベースの技術を選定しておいたほうが苦労は少ないかと思います。

大前提として使用するライブラリに依るところが大きいですが、サーバーコンポーネント前提で設計されているライブラリはあまりなく、何も考えずに混ぜると結局use clientだらけになってしまい、サーバーコンポーネントの良さを引き出せないことが多いと思います。
(多くの場合クライアントでのステートやRefに依存するコンポーネントが多いため。)

また上記に関連して、Exampleの実装をそのまま使えないこともあります。
弊チームでは shadcn-ui を採用しましたが、DataTableのExampleを見るとTanstack Tableを用いたクライアントサイドベースの実装になっています。
一方でLearn Next.jsを見てみるとサーバーサイドでページングやフィルタを行う実装になっており、それぞれを上手くマージする必要が出てきます。

どちらの実装にするかは要件次第ですが、例えば弊チームのようにNext.jsアプリケーションの外部に別途APIがあり、そのAPIがページングやフィルタの機構を持っているような場合、サーバーサイドでの実装に倒すことでクライアントでの状態管理をかなり省けます。

あと個人的な経験としては、例えばクエリパラメータとクライアントのステートを同期しないといけないような要件があったりすると結構手間だと感じるので、こういった場合にもサーバーサイドでの解決が刺さりそうだなと思っています。

余談 ローディング状態の管理

このあたりは余談ということで、前提知識の補完のような形で差し込んでみました。

App RouterというよりはSuspenseの話になりますが、ローディング状態の実装方法が従来の状態管理ベースとは異なっており、それによってコンポーネントの責務が変わるというところが地味に重要な気がしています。

また、ライブラリによってはコンポーネントに loadingのようなプロパティが生えていることがあり、こういったものは従来の状態管理で実装することを前提にしているので注意が必要です。
リッチなコンポーネントになるほどこういったパターンが多い気がしています。

ex. Data Grid - MUI X
https://mui.com/x/react-data-grid/state/

余談2 Skeleton UI


Next.jsのドキュメントを見ているとよく出てくる概念です。

スライド画像ではYouTubeの例を貼っています。
待機状態でもデータフェッチ後のレイアウトが見えるようにしようというものです。

これによってユーザー体験が良くなるのは理解していますが、Skeleton部分は自分たちで別途実装する必要があったりするので、弊チームでは今のところtoB向けだと割り切ってインジケータを表示するのみに留めています。

このあたりは何を優先するかで取捨選択する部分にしても良いのかなと思っています。

React Hook Form との相性

次にReact Hook Formとの相性です。
ほぼデファクトで選定される印象ですが、Server Actionsとの相性はそこまで良くなさそうです。

というのも、React Hook Formはクライアントの状態管理のみをスコープとしているライブラリなので、Server Actionsで実装する場合、サーバーサイドでのバリデーションを別途行う必要が出てきます。

shadcn-uiを採用する場合、デフォルトだとReact Hook Formと密結合しているので少し手をいれる必要が出てきます。

弊チームでは割り切ってバリデーションはzodを使って別途実装し、かつ以下のIssueにあるようなハックを入れて対応しています。

https://github.com/react-hook-form/react-hook-form/issues/10391#issuecomment-2064912244

今のところはこれで問題ないですが、様子を見つつ問題が発生しそうであればConfirmなど、Server Actionsに対応しているライブラリに置き換えることも検討する必要があるかと思います。

このあたりもやろうと思えば柔軟に交換できるshadcn-uiはいいですね。

まとめ(所感)

まだまだ枯れきっていない技術ではあるので苦労は多かったです。

個人的にはSkeleton UIの話やレイアウトシフト、プログレッシブエンハンスメントなど、toC指向を重視したフレームワークだと感じています。
なのでtoBなどではあまりドキュメントに杓子定規にならず、必要に応じて取捨選択するのが現実的で良さそうだと思っています。

これまでのスタックで満足できているのであれば無理に採用する必要はないかと思っていますが、上手く使えば責務の分離など、カオスになりがちなフロントエンドに一定の方針を強いることができるので、そういったところがApp Routerの良さであると今のところは考えています。

最後に

懇親会でも色々な方と交流できて楽しかったです。
ご参加いただいた皆様、このような機会をくださった運営の皆様、本当にありがとうございました。
勉強会は今後も継続していくと思いますので、今後も是非奮ってご参加ください。

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.